<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // Promise的优点:
    // 有了Promise对象，就可以将异步操作以同步操作的流程表达出来，避免了层层嵌套的回调函数。此外，Promise对象提供统一的接口，使得控制异步操作更加容易。

    // Promise对象(实例化对象)的方法
    // then(resolveHandler,rejectHandler)     Promise 对象添加状态改变时的回调函数
    // resolveHandler()    将Promise对象的状态 由 pending(进行中) 变为 fulfilled(已成功)执行此回调函数
    // rejectHandler()    将Promise对象的状态 由 pending(进行中) 变为 rejected(已失败)执行此回调函数

    // 返回值:  新的Promise对象  -> 链式操作

    // 注意:
    // then() 调用发生在异步代码执行之前 => 可以理解为then()提前指定了状态改变时要执行的内容(回调函数), 等Promise状态改变后 -> 执行对应的回调函数
    // resolveHandler()  rejectHandler() 都有一个形式参数 -> 用于接收Promise对象中存储的数据


    // 什么时候Promise对象的状态会变为已失败
    // 1. 当reject() 被调用时  => Promise对象的状态会变为已失败状态
    // 2. new Promise()中的回调函数,在执行过程中有try...catch 异常捕获机制 -> 如果回调函数执行时出错 => Promise对象会变为已失败 => 错误的信息(err对象)会作为Promise对象的数据存储


    // catch(rejectHandler)    用于指定发生错误时的回调函数。  (catch方法就是基于then方法封装的,只指定了错误发生时的回调函数)

    // 可以理解为
    // Promise.prototype.catch = function (rejectHandler) {
    //     // this -> 调用此方法的实例化对象(Promise对象)
    //     return this.then(null, rejectHandler);
    // }


    // finally()     无论Promise对象的状态是已成功,还是已失败  -> 都会执行的回调函数

    // 可以理解为
    // Promise.prototype.finally = function (finallyCallback) {
    //     // this -> 调用此方法的实例化对象(Promise对象)
    //     return this.then(function () {
    //         finallyCallback();
    //     }, function () {
    //         finallyCallback();
    //     });
    // }


</script>
<script>


    // then()  catch()  finally()  => 返回值都是新的Promise对象  -> 后面可以跟链式操作

    //  后面的Promise对象,需要等待前面的Promise对象状态改变之后,才能改变状态(后面的依赖前面的)

    // Promise对象的链式操作规律:
    // 1. 如果then()中不指定成功,失败时的回调函数, Promise对象的状态和存储的数据会链式向后传递 
    // 2. 如果then()中指定成功,失败时的回调函数,  先执行回调函数,等回调函数执行完毕(不出错), 后续的Promise对象也会变为已成功(此时回调函数的结果会作为后续的Promise实例的结果存储), 如果回调函数执行过程中出现错误,后续的Promise对象会变为已失败, 错误的信息(err) 会作为数据存储
    //    技巧: Promise对象可以通过then()方法指定多个回调函数,后面的回调函数可以接收前面的回调函数的返回值(返回值不是一个Promise对象),catch可以捕获整个链式操作过程中的错误

    // 3.  Promise对象可以通过then()方法指定多个回调函数,如果回调函数的返回值是一个Promise对象,后续的Promise对象需要等待该Promise对象状态改变之后,再改变状态(后续的Promise对象的状态和数据,依赖于返回的Promise对象)
    //   技巧:  Promise对象可以通过then()方法指定多个回调函数,如果回调函数的返回值是一个Promise对象,等该Promise对象状态改变之后在向后传递


    var p = new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(1);  // {<fulfilled>:1}
            // reject(2);  // {<rejected>:2}
        }, 1000)
    })


    // p(1s变状态)  -> p1  -> p2  -> p3

    // 只指定成功时执行的回调函数, 没有指定失败时执行的回调函数 -> 失败的状态和存储的数据会依次 向后传递
    p.then(function (arg) {
        console.log("fulfilled:", arg); // 1

        var N1 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve(2);  // {<fulfilled>:2}
            }, 2000)
        })


        return N1;  // {<pending>:undefined}  => 2s后  {<fulfilled>:2}
    }).then(function (arg) {
        console.log("fulfilled:", arg); // 2


        var N2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve(3);  // {<fulfilled>:3}
            }, 3000)
        })

        return N2;   // {<pending>:undefined}  => 3s后  {<fulfilled>:3}
    }).then(function (arg) {
        console.log("fulfilled:", arg);  // 3
    }).catch(function (err) {
        console.log("rejeced", err);
    })



</script>

</html>